using System;
using System.Collections.Generic;
using Castle.ActiveRecord;
using Castle.Components.Validator;

namespace ValidationFramework.ActiveRecord
{
	/// <summary>
	/// Base class that provides minimal validation logic.
	/// </summary>
	[Serializable]
	public abstract class ActiveRecordValidatableBase : ActiveRecordBase, NHibernate.Classic.IValidatable, IValidatable
	{
	


		#region Constructors

        /// <inheritdoc/>
		protected ActiveRecordValidatableBase()
		{
			PropertyValidationManager = ValidationManagerFactory.GetPropertyValidationManager(this);
		
		}

		#endregion


		#region Properties


		/// <summary>
		/// An <see cref="object"/> to pass as the context parameter when calling <see cref="Rule.Validate"/>. The default is null.
		/// </summary>
		public virtual object Context
		{
			get
			{
				return PropertyValidationManager.Context;
			}
			set
			{
				PropertyValidationManager.Context = value;
			}
		}


		/// <summary>
		/// Gets the rule set to validate.
		/// </summary>
		/// <remarks>Will be a null to validate all <see cref="Rule"/>s.</remarks>
		public virtual string RuleSet
		{
			get
			{
				return PropertyValidationManager.RuleSet;
			}
			set
			{
				PropertyValidationManager.RuleSet = value;
			}
		}


		/// <summary>
		/// Gets a <see cref="IList{T}"/> containing all <see cref="ValidationError"/> in error.
		/// </summary>
		public virtual IList<ValidationError> ValidatorResultsInError
		{
			get
			{
				return PropertyValidationManager.ValidatorResultsInError;
			}
		}


		/// <summary>
		/// Gets the <see cref="ValidationFramework.PropertyValidationManager"/>.
		/// </summary>
		public virtual MemberValidationManager PropertyValidationManager
		{
			get;
			private set;
		}


		/// <summary>
		/// Gets a <see lanword="bool"/> indicating if the current state is valid.
		/// </summary>
		/// <remarks>
		/// Base behavior is to validate all properties and return boolean value.
		/// Sub-class can override this if, for example, they are validating on the fly.
		/// </remarks>
		public virtual bool IsValid
		{
			get
			{
					PropertyValidationManager.ValidateAll();
				return PropertyValidationManager.IsValid;
			}
		}


		/// <summary>
		/// Gets a <see see="IList{T}"/> of <see langword="string"/>s that contain all the error messages.
		/// </summary>
		public virtual IList<string> ErrorMessages
		{
			get
			{
				return ResultFormatter.GetErrorMessages(PropertyValidationManager.ValidatorResultsInError);
			}
		}


		#endregion


		#region Methods

		/// <summary>
		/// Throws an exception explaining why the save or update cannot be executed when fields are not ok to pass.
		/// </summary>
		/// <exception cref="ValidationException"><see cref="IsValid"/> is <c>false</c>.</exception>
		void NHibernate.Classic.IValidatable.Validate()
		{
			if (!IsValid)
			{
				var errorsList = new List<string>(ErrorMessages);
				throw new ValidationException(
					"Can't save or update as there is one (or more) field that has not passed the validation test",
					errorsList.ToArray());
			}
		}

		#endregion
	}
}